import pytest
from unittest.mock import MagicMock, patch


# 模拟API客户端（零网络调用）
class CvmClient:
    def __init__(self):
        self.responses = {
            # 基础响应
            "Success": {"Response": {"RequestId": "mock-req-123"}},

            # 参数验证错误
            "InvalidParameter": {"Response": {"Error": {"Code": "InvalidParameter"}}},
            "InvalidInstanceId": {"Response": {"Error": {"Code": "InvalidInstanceId"}}},
            "InvalidPeriod": {"Response": {"Error": {"Code": "InvalidPeriod"}}},
            "InvalidParameterValue": {"Response": {"Error": {"Code": "InvalidParameterValue"}}},

            # 资源状态错误
            "OperationDenied.InstanceOperationInProgress": {
                "Response": {"Error": {"Code": "OperationDenied.InstanceOperationInProgress"}}
            },
            "UnsupportedOperation.InstanceStateFreezing": {
                "Response": {"Error": {"Code": "UnsupportedOperation.InstanceStateFreezing"}}
            },
            "UnsupportedOperation.InstanceStateStopping": {
                "Response": {"Error": {"Code": "UnsupportedOperation.InstanceStateStopping"}}
            },

            # 权限与配额错误
            "InvalidAccount.InsufficientBalance": {
                "Response": {"Error": {"Code": "InvalidAccount.InsufficientBalance"}}
            },
            "InvalidAccount.UnpaidOrder": {
                "Response": {"Error": {"Code": "InvalidAccount.UnpaidOrder"}}
            },
            "UnsupportedOperation.InstanceMixedZoneType": {
                "Response": {"Error": {"Code": "UnsupportedOperation.InstanceMixedZoneType"}}
            },

            # 特殊限制错误
            "UnsupportedOperation.SpecialInstanceType": {
                "Response": {"Error": {"Code": "UnsupportedOperation.SpecialInstanceType"}}
            },
            "UnsupportedOperation.InvalidDiskBackupQuota": {
                "Response": {"Error": {"Code": "UnsupportedOperation.InvalidDiskBackupQuota"}}
            }
        }

    def renew_instance(self, instance_id, period=1, renew_flag="NOTIFY_AND_AUTO_RENEW"):
        # 模拟参数校验逻辑
        if not instance_id or not isinstance(instance_id, str):
            return self.responses["InvalidParameter"]
        if period < 1 or period > 36:
            return self.responses["InvalidPeriod"]
        if renew_flag not in ["NOTIFY_AND_AUTO_RENEW", "NOTIFY_AND_MANUAL_RENEW"]:
            return self.responses["InvalidParameterValue"]

        # 模拟资源状态检查
        if instance_id == "ins-running":
            return self.responses["OperationDenied.InstanceOperationInProgress"]
        if instance_id == "ins-frozen":
            return self.responses["UnsupportedOperation.InstanceStateFreezing"]
        if instance_id == "ins-stopped":
            return self.responses["UnsupportedOperation.InstanceStateStopping"]

        # 模拟权限/配额检查
        if instance_id == "ins-insufficient-balance":
            return self.responses["InvalidAccount.InsufficientBalance"]
        if instance_id == "ins-unpaid-order":
            return self.responses["InvalidAccount.UnpaidOrder"]
        if instance_id == "ins-mixed-zone":
            return self.responses["UnsupportedOperation.InstanceMixedZoneType"]

        # 模拟特殊限制
        if instance_id == "ins-special":
            return self.responses["UnsupportedOperation.SpecialInstanceType"]
        if instance_id == "ins-with-backup":
            return self.responses["UnsupportedOperation.InvalidDiskBackupQuota"]

        # 默认成功响应
        return self.responses["Success"]


# 测试用例
class TestRenewInstances:
    @pytest.fixture
    def client(self):
        return CvmClient()

    # 参数验证类错误
    @pytest.mark.parametrize("instance_id,period,renew_flag,expected_code", [
        ("", 1, "NOTIFY_AND_AUTO_RENEW", "InvalidParameter"),  # 空实例ID
        (None, 1, "NOTIFY_AND_AUTO_RENEW", "InvalidParameter"),  # None类型
        ("ins-123", 0, "NOTIFY_AND_AUTO_RENEW", "InvalidPeriod"),  # 无效时长
        ("ins-123", 37, "NOTIFY_AND_AUTO_RENEW", "InvalidPeriod"),  # 超长时长
        ("ins-123", 1, "INVALID_FLAG", "InvalidParameterValue"),  # 无效标志
    ])
    def test_invalid_params(self, client, instance_id, period, renew_flag, expected_code):
        response = client.renew_instance(instance_id, period, renew_flag)
        assert response["Response"]["Error"]["Code"] == expected_code

    # 资源状态类错误
    @pytest.mark.parametrize("instance_id,expected_code", [
        ("ins-running", "OperationDenied.InstanceOperationInProgress"),
        ("ins-frozen", "UnsupportedOperation.InstanceStateFreezing"),
        ("ins-stopped", "UnsupportedOperation.InstanceStateStopping"),
    ])
    def test_resource_status(self, client, instance_id, expected_code):
        response = client.renew_instance(instance_id)
        assert response["Response"]["Error"]["Code"] == expected_code

    # 权限与配额类错误
    @pytest.mark.parametrize("instance_id,expected_code", [
        ("ins-insufficient-balance", "InvalidAccount.InsufficientBalance"),
        ("ins-unpaid-order", "InvalidAccount.UnpaidOrder"),
        ("ins-mixed-zone", "UnsupportedOperation.InstanceMixedZoneType"),
    ])
    def test_auth_and_quota(self, client, instance_id, expected_code):
        response = client.renew_instance(instance_id)
        assert response["Response"]["Error"]["Code"] == expected_code

    # 特殊限制类错误
    @pytest.mark.parametrize("instance_id,expected_code", [
        ("ins-special", "UnsupportedOperation.SpecialInstanceType"),
        ("ins-with-backup", "UnsupportedOperation.InvalidDiskBackupQuota"),
    ])
    def test_special_restrictions(self, client, instance_id, expected_code):
        response = client.renew_instance(instance_id)
        assert response["Response"]["Error"]["Code"] == expected_code

    # 正常用例
    def test_success(self, client):
        response = client.renew_instance("ins-123", 1)
        assert response["Response"]["RequestId"] == "mock-req-123"
        assert "Error" not in response["Response"]


# 执行测试
if __name__ == "__main__":
    pytest.main(["-v", "--color=yes"])